package com.nova.bluetooth.ui.ai.aiNote;

import android.text.TextUtils;
import android.util.Pair;

import androidx.lifecycle.MutableLiveData;

import com.google.firebase.crashlytics.buildtools.reloc.org.apache.commons.io.FileUtils;
import com.google.firebase.crashlytics.buildtools.reloc.org.apache.http.entity.FileEntity;
import com.kunminx.architecture.domain.message.MutableResult;
import com.nova.bluetooth.base.BaseNovaViewModel;
import com.nova.bluetooth.helpUtils.FileUtil;
import com.nova.bluetooth.helpUtils.LogUtil;
import com.nova.bluetooth.helpUtils.StorageUtil;
import com.nova.bluetooth.helpUtils.WavFileInfoReader;

import java.io.File;

import io.microshow.rxffmpeg.RxFFmpegCommandList;
import io.microshow.rxffmpeg.RxFFmpegInvoke;
import io.microshow.rxffmpeg.RxFFmpegSubscriber;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class AudioFileViewModel extends BaseNovaViewModel {

    public MutableLiveData<String> mFFmpegAudioFilePath = new MutableLiveData<>();
    public final MutableResult<Pair<Boolean, String>> showProgressDialog = new MutableResult<>();
    public void dealwithAudioFile(File file) {
        if (!isFileValid(file.getPath())) {
            return;
        }
        showProgressDialog.postValue(Pair.create(true, ""));
        Disposable subscribe = Observable.create((ObservableOnSubscribe<String>) emitter -> {
                    // 外部导入，拷贝文件到内部存储
                    String audioDir = StorageUtil.getAudioDir();
                    String path = audioDir + "/" + file.getName();
                    File outputFile = new File(path);

                    String outputFilePath;
                    if (outputFile.exists()) {
                        LogUtil.d("已存在" + outputFile);
                        outputFilePath = audioDir + "/" + System.currentTimeMillis() + "_" + file.getName();
                    } else {
                        outputFilePath = audioDir + "/" + file.getName();
                    }


                    /********************************* 音频转换start *********************************/
                    try {
                        final String finalOutputFilePath = outputFilePath
                                .replaceAll("\\.mp3", "\\.wav")
                                .replaceAll("\\.m4a", "\\.wav");

                        LogUtil.d("ffmpeg输出路径：" + finalOutputFilePath);

                        Pair<Integer, Integer> audioInfo;
                        if (file.getPath().endsWith(".m4a")) {
                            // m4a 获取通道/采样率不准，直接通过指令全都转换一下
                            audioInfo = Pair.create(2, 48000);
                        } else {
                            audioInfo = WavFileInfoReader.getChannelFormatAndSampleRate(file.getPath());
                        }
                        LogUtil.d("音频信息：通道/采样率 " + audioInfo);

                        boolean changeChannels = audioInfo.first != 1;
                        boolean changeSampleRate = audioInfo.second != 16000;
                        boolean isWav = outputFilePath.toLowerCase().endsWith(".wav");

                        String[] command;
                        if (changeChannels || changeSampleRate) {
                            command = generateFFmpegCommand(file.getPath(), finalOutputFilePath, changeChannels, changeSampleRate);
                        } else if (!isWav) {
                            command = generateFFmpegCommand(file.getPath(), finalOutputFilePath, false, false);
                        } else {
                            command = null;
                            FileUtils.copyFile(file, new File(finalOutputFilePath));
                        }

                        if (command != null) {
                            LogUtil.d("生成的FFmpeg命令: " + String.join(" ", command));
                            RxFFmpegInvoke.getInstance().runCommandRxJava(command).subscribe(new RxFFmpegSubscriber() {
                                @Override
                                public void onFinish() {
                                    LogUtil.d("转换成功");
                                    emitter.onNext(finalOutputFilePath);
                                }

                                @Override
                                public void onProgress(int progress, long progressTime) {
                                    LogUtil.d("progress = " + progress + ", progressTime = " + progressTime);
                                }

                                @Override
                                public void onCancel() {
                                    LogUtil.d("转换取消");
                                }

                                @Override
                                public void onError(String message) {
                                    LogUtil.e("转换错误: " + message);
                                }
                            });
                        } else {
                            LogUtil.d("文件符合语音识别编码信息，不转换，直接拷贝到内部存储");
                            emitter.onNext(file.getPath());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        FileUtils.copyFile(file, new File(outputFilePath));
                        emitter.onNext(outputFilePath);
                    }

                    /********************************* 音频转换end *********************************/


                })
                .subscribeOn(Schedulers.io())
                .flatMap((Function<String, ObservableSource<Long>>) path -> {
                    LogUtil.d("test==>文件转换生成完成，文件路径==》" + path);
                    return Observable.fromCallable(() -> {
                        // 在IO线程中执行数据库操作
                        if (TextUtils.isEmpty(path)) {
                            return -1L;
                        } else {
                            mFFmpegAudioFilePath.postValue(path);
                            return 1L;
                        }
                    }).subscribeOn(Schedulers.io());
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(result -> {
                    if (result > 0L) {
                        LogUtil.d("test==>文件转换成功过了");
                        showProgressDialog.postValue(Pair.create(false, "文件转换成功过了"));
                    }
                }, throwable -> {
                    LogUtil.e("操作失败:" + throwable.getMessage());
                    showProgressDialog.postValue(Pair.create(false, throwable.getMessage()));
                });
        register(subscribe);
    }

    private boolean isFileValid(String filePath) {
        if (!FileUtil.isFilePathValid(filePath)) {
            return false;
        }
        return FileUtil.isFilePathSizeValid(filePath);
    }

    /**
     * 生成FFmpeg命令
     *
     * @param inputPath
     * @param outputPath
     * @param changeChannels
     * @param changeSampleRate
     * @return
     */
    private String[] generateFFmpegCommand(String inputPath,
                                           String outputPath,
                                           boolean changeChannels,
                                           boolean changeSampleRate) {
        RxFFmpegCommandList cmdList = new RxFFmpegCommandList();
        cmdList.append("-i").append(inputPath);

        if (changeChannels) {
            cmdList.append("-ac").append("1");
        }

        if (changeSampleRate) {
            cmdList.append("-ar").append("16000");
        }

        cmdList.append(outputPath);
        return cmdList.build();
    }

}
